Springboot入门

SpringBoot简介

  • 简化Spring应用开发的一个框架

  • 整个Spring技术栈的一个大整合

  • J2EE开发的一站式解决方案

微服务

2014,martin fowler

微服务:架构风格(服务微化)

一个应用应该是一组小型服务,可以通过HTTP的方式进行互通。

  • 单体应用:ALL IN ONE

  • 微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;

微服务文档

HelloWorld

功能:浏览器发送hello请求,服务器接受请求并处理,响应“Hello World!”字符串。

创建maven项目

导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.gxk</groupId>
<artifactId>spring-boot-01-helloworld</artifactId>
<version>1.0-SNAPSHOT</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>

编写主程序

1
2
3
4
5
6
7
8
9
10
11
/**
* 声明一个SpringBoot主程序类
*/
@SpringBootApplication

public class HelloWorldMainApplication {
public static void main(String[] args) {
// 启动SpringBoot应用
SpringApplication.run(HelloWorldMainApplication.class, args);
}
}

编写Controller、Service

1
2
3
4
5
6
7
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello World!";
}
}

运行

直接右键运行主程序类即可

打包

  1. maven中导入插件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!-- 可将应用打包成可执行jar包的插件 -->
    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>
  2. 点击idea右侧工具栏中的Maven,运行”项目名-Lifecycle-package

  3. 将target目录下jar包拷出,使用cmd的”java -jar xxx.jar“运行即可

HelloWorld探究

POM文件

  1. 父项目

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
    <relativePath/>
    </parent>

    他的父项目是:
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring‐boot‐dependencies</artifactId>
    <version>2.1.6.RELEASE</version>
    <relativePath>../../spring‐boot‐dependencies</relativePath>
    </parent>
    他来真正管理Spring Boot应用里面的所有依赖版本

Spring Boot的版本仲裁中心。

以后我们导入依赖默认是不需要写版本(没有在dependencies里面管理的依赖自然需要声明版本号)

  1. 启动器

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

spring-boot-starter:springboot的场景启动器,帮我们导入了指定模块(如:web)正常运行所依赖的组件。

Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器),只需要在项目里面引入这些starter,相关场景的所有依赖都会导入进来。需要什么功能就导入什么场景启动器

主程序类

1
2
3
4
5
6
7
8
9
10
/**
* 声明一个SpringBoot主程序类
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// 启动SpringBoot应用
SpringApplication.run(HelloWorldMainApplication.class, args);
}
}

@SpringBootApplication:用来标注SpringBoot的主程序类,SpringBoot
应该运行这个类的main方法来启动SpringBoot应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {...}
  • @SpringBootConfiguration:标注SpringBoot的配置类

    • @Configuration:标注配置类(Spring)
  • @EnableAutoConfiguration:开启自动配置

    1
    2
    3
    @AutoConfigurationPackage
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {...}
  • @AutoConfigurationPackage:自动配置包

    1
    2
    3
    @Import({Registrar.class})
    public @interface AutoConfigurationPackage {
    }
1
2
3
4
5
6
7
8
9
10
11
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {

}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
}
}
**将主配置类所在包及下面所有子包里面的所有组件扫描到Spring容器。**
  • @Import({AutoConfigurationImportSelector.class})

    AutoConfigurationImportSelector:导入哪些组件的选择器。

    将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中。

    会给容器中导入非常多的自动配置类(xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件。

    Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。以前我们需要自己配置的东西,自动配置类都帮我们。

使用Spring Initializer快速创建SpringBoot项目

IDE都支持使用Spring的项目创建向导快速创建一个Spring Boot项目
选择我们需要的模块;向导会联网创建Spring Boot项目
默认生成的Spring Boot项目

  • 主程序已经生成好了,我们只需要我们自己的逻辑

  • resources文件夹中目录结构

    • static:保存所有的静态资源(js/css/images)

    • templates:保存所有的模板页面(SpringBoot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面,可以使用模板引擎(如:freemarker、thymeleaf))

    • application.properties:SpringBoot应用的配置文件,可以修改一些默认设置

配置文件

配置文件

Spring Boot使用全局配置文件,配置文件名是固定的:

  • application.properties
  • application.yml

配置文件作用:修改Spring Boot在底层封装好的默认值。

YAML(YAML AIN’T Markup Language):

是一个标记语言,

又不是一个标记语言。

以前的配置文件,大多数使用的是 xxx.xml文件。

yaml以数据为中心,比json、xml等更适合做配置文件。

  • YMAL:

    1
    2
    server:
    port: 9000
  • xml:

    1
    2
    3
    <server>
    <port>9000</port>
    </server>

YAML语法

基本语法

k:(空格)v:表示一堆键值对(空格必须有);

以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一层级的:

1
2
3
server:
port: 9000
path: /hello

属性和值也是大小写敏感。

值的写法

字面量:普通的值(数字,字符串,布尔)

k: v:字面量直接来写

  • 字符串默认不用加上单引号或者双引号

  • “”:双引号 不会转义字符串里的特殊字符;特殊字符会作为本身想要表示的意思如:name:"zhangsan\n lisi" 输出:zhangsan换行 lisi

  • ‘’:单引号 会转义特殊字符,特殊字符最终只是一个普通的字符串数据

    如:name:'zhangsan\n lisi' 输出:zhangsan\n lisi

  • 对象、Map(属性和值)键值对

    1
    2
    3
    frends:
    lastName: zhangsan
    age: 20

行内写法:

1
friends: {lastName: zhangsan,age: 18}
  • 数组(List、Set): 用-表示数组中的一个元素

    1
    2
    3
    4
    pets:
    cat
    dog
    pig

行内写法:

1
pets: [cat,dog,pig]
  • 组合变量

    多个组合到一起

配置文件值注入

@ConfigurationProperties

  1. application.yml 配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    person:
    age: 18
    boss: false
    birth: 2017/12/12
    maps: {k1: v1,k2: 12}
    lists:
    - lisi
    - zhaoliu
    dog:
    name: wangwang
    age: 2
    last-name: wanghuahua
  2. application.properties 配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    person.age=12
    person.boss=false
    person.last-name=张三
    person.maps.k1=v1
    person.maps.k2=v2
    person.lists=a,b,c
    person.dog.name=wanghuahu
    person.dog.age=15

idea配置文件编码为utf-8,properties文件编码默认GBK,所以中文输出乱码。

解决方法:settings → file encoding → [property → utf-8,勾选转成ascii]

  1. javaBean

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
    * 将配置文件的配置每个属性的值,映射到组件中
    * @ConfigurationProperties:告诉SpringBoot将文本的所有属性和配置文件中的相关配置进行绑定
    * prefix = "person" 与配置文件进行一一映射
    *
    * 只有这个组件是容器中的组件,才能提供到容器中
    */
    @Component
    @ConfigurationProperties(prefix = "person")
    public class Person {
    private String lastName;
    private Integer age;
    private Boolean boss;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
    }

导入配置文件处理器,以后编写配置就有提示了

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐configuration‐processor</artifactId>
<optional>true</optional>
</dependency>

@Value注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class Person {
/**
* 相当于:
* <bean class="Person">
* <property name="lastName" value="字面量/${key}从环境变量/#{spEL}"></property>
* </bean>
*/
@Value("${person.last-name}")
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
@ConfigurationProperties @Value
功能 批量注入配置文件属性 单个指定
松散绑定(语法) 支持 不支持
spEL 不支持 支持
JSR303校验 支持 不支持
复杂类型 支持 不支持

松散语法:javaBean中last-name(或者lastName) → application.properties中的last-name

spEL语法:#{11*2}

JSR303:@Value会直接忽略,校验规则

JSR303校验

1
2
3
4
5
6
7
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Email
private String lastName;
}

复杂类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class Person {
/**
* <bean class="Person">
* <property name="lastName" value="字面量/${key}从环境变量/#{spEL}"></property>
* </bean>
*/
private String lastName;
private Integer age;
private Boolean boss;
@Value("${person.maps}") // 会报错,@Value不支持复杂类型

private Map<String,Object> maps;
}

使用场景分析

  • 如果我们只是在某个业务逻辑中获取一下配置文件的某一项值,使用@Value

  • 如果专门编写了一个javaBean和配置文件进行映射,我们直接使用@ConfigurationProperties

例如:

  1. 编写新的Controller文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @RestController
    public class HelloController {

    @Value("${person.last-name}")
    private String name;

    @RequestMapping("/hello")
    public String sayHello() {
    return "Hello"+ name;
    }
    }
  2. 配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    person.age=12
    person.boss=false
    person.last-name=李四
    person.maps.k1=v1
    person.maps.k2=v2
    person.lists=a,b,c
    person.dog.name=wanghuahu
    person.dog.age=15
  3. 运行结果

    Hello 李四

其他注解

  • @PropertySource

    作用:加载指定的properties配置文件

    举例

    1. 新建一个person.properties文件

      1
      2
      3
      4
      5
      6
      7
      8
      person.age=12
      person.boss=false
      person.last-name=李四
      person.maps.k1=v1
      person.maps.k2=v2
      person.lists=a,b,c
      person.dog.name=wanghuahu
      person.dog.age=15
  1. 在javaBean中加入@PropertySource注解

    1
    2
    3
    4
    5
    6
    @PropertySource(value = {"classpath:person.properties"})
    @Component
    @ConfigurationProperties(prefix = "person")
    public class Person {
    private String lastName;
    }
  • @ImportResource

    作用:导入Spring配置文件,并且让这个配置文件生效

    举例

    1. 新建一个Spring的配置文件,bean.xml

      1
      2
      3
      4
      5
      6
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
      <bean id="HelloService" class="com.wdjr.springboot.service.HelloService"></bean>
      </beans>
  1. 编写测试类,检查容器是否加载Spring配置文件写的bean

    1
    2
    3
    4
    5
    6
    7
    8
    @Autowired
    ApplicationContext ioc;

    @Test
    public void testHelloService(){
    boolean b = ioc.containsBean("HelloService");
    System.out.println(b);
    }
  1. 运行结果

    false

  2. 使用@ImportResource注解

    将@ImportResource标注在主配置类上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @ImportResource(locations={"classpath:beans.xml"})
    @SpringBootApplication
    public class SpringBoot02ConfigApplication {

    public static void main(String[] args {
    SpringApplication.run(SpringBoot02ConfigApplication.class, args);

    }
    }
  1. 运行结果

    true

缺点:每次指定xml文件太麻烦

SpringBoot推荐给容器添加组件的方式(@Configuration + @Bean):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @Configuration:指明当前类是一个配置类;就是来代替之前的Spring配置文件
*
* 在配置文件中用<bean></bean>标签添加组件
*/
@Configuration
public class MyAppConfig {
// 将方法的返回值添加到容器中,这个组件的id默认为方法名
@Bean
public HelloService helloService01() {

System.out.println("配置类给容器添加了HelloService组件");
return new HelloService();
}
}
1
2
3
4
5
6
7
8
@Autowired
ApplicationContext ioc;

@Test
public void testHelloService(){
boolean b = ioc.containsBean("helloService01");
System.out.println(b);
}

配置文件占位符

随机数

1
2
${random.value} 、${random.int}、${random.long}、
${random.int(10)}、${random.int[100,200]}

获取配置值

1
2
3
4
5
6
7
8
person.age=${random.int}
person.boss=false
person.last-name=张三${random.uuid}
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=${person.last-name}'s wanghuahu
person.dog.age=15

存在以下两种情况:

没有声明person.last-name会报错,新声明的需要加默认值。

1
2
3
4
5
6
7
8
person.age=${random.int}
person.boss=false
person.last-name=张三${random.uuid}
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=${person.hello:hello}'s wanghuahu
person.dog.age=15

输出结果hello's wanghuahua

Profile

多Profile文件

我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml

  • application.properties
  • application-dev.properties
  • application-prod.properties

默认使用application.properties

application.properties配置文件指定

1
spring.profiles.active=dev

YAML文档块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server:
port: 8081
spring:
profiles:
active: dev

---

server:
port: 9000
spring:
profiles: dev

---

server:
port: 80
spring:
profiles: prod

激活指定profile

  1. 在配置文件中激活

    1
    spring.profiles.active=dev
  2. 命令行

    java -jar xxx.jar --spring.profiles.active=dev

  3. 虚拟机参数

    -Dspring.profiles.active=dev

加载配置文件位置

SpringBoot启动扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件

  • file:./config/
  • file./
  • classpath:/config/
  • classpath:/

优先级从高到低顺序,高优先级会覆盖低优先级的相同配置,互补配置

也可以通过spring.config.location来改变默认配置文件位置 。

项目打包好了以后,可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认的配置文件会共同起作用,互补配置

java -jar xxx.jar --spring.config.location=E:/work/application.properties

运维比较有用,从外部加载,不用修改别的文件

外部配置的加载顺序

SpringBoot也可以从以下位置加载配置,优先级从高到低,高优先级覆盖低优先级,可以互补。

  1. 命令行参数

    java -jar xxx.jar –server.port=9005 –server.context-path=/abc

  2. 来自java:comp/env的JNDI属性

  3. java系统属性(System.getProperties())

  4. 操作系统环境变量

  5. RandomValuePropertySource配置的random.*属性值

  6. jar包外部的application-{profile}.properties 或 application.yml(带Spring.profile)配置文件

  7. jar包内部的application-{profile}.properties 或 application.yml(带Spring.profile)配置文件

  8. jar包外部的application.properties 或 application.yml(带Spring.profile)配置文件

  9. jar包内部的application.properties 或 application.yml(不带spring.profile)配置文件

  10. @Configuration注解类的@PropertySource

  11. 通过SpringApplication.setDefaultProperties指定的默认属性

自动配置

Spring的所有配置参数

自动配置原理

  1. SpringBoot启动的时候加载主配置类,开启自动配置功能,@EnableAutoConfiguration

  2. @EnableAutoConfiguration 作用:

    • 利用AutoConfigurationImportSelector给容器中导入一些组件?

    • 可以查看selectImports()方法的内容

    • List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置

      • 1
        2
        3
        4
        SpringFactoriesLoader.loadFactoryNames()
        扫描所有jar包类路径下的 MATA-INF/spring.factories
        把扫描到的这些文件的内容包装成properties对象
        从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加到容器中

将类路径下 MATE-INF/spring.factories里面配置的所有的EnableAutoConfiguration的值加入到了容器中。

  1. 每一个自动配置类进行自动配置功能

  2. HttpEncodingAutoConfiguration 为例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    @Configuration //表示是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
    @EnableConfigurationProperties({HttpEncodingProperties.class})//启动指定类的Configurationproperties功能;将配置文件中的值和HttpEncodingProperties绑定起来了;并把HttpEncodingProperties加入ioc容器中
    @ConditionalOnWebApplication//根据不同的条件,进行判断,如果满足条件,整个配置类里面的配置就会失效,判断是否为web应用;
    (
    type = Type.SERVLET
    )
    @ConditionalOnClass({CharacterEncodingFilter.class})//判断当前项目有没有这个类,解决乱码的过滤器
    @ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
    )//判断配置文件是否存在某个配置 spring.http.encoding,matchIfMissing = true如果不存在也是成立,即使不配置也生效
    public class HttpEncodingAutoConfiguration {
    //给容器添加组件,这个组件的值需要从properties属性中获取
    private final HttpEncodingProperties properties;
    //只有一个有参数构造器情况下,参数的值就会从容器中拿
    public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
    this.properties = properties;
    }

    @Bean

    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
    CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
    filter.setEncoding(this.properties.getCharset().name());
    filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpEncodingProperties.Type.REQUEST));
    filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpEncodingProperties.Type.RESPONSE));
    return filter;
    }
  3. 所有在配置文件中能配置的属性都是在xxxProperties类中封装着,配置文件能配置什么就可以参照某个功能对应的这个属性类。

    1
    2
    3
    @ConfigurationProperties(prefix = "spring.http.encoding") // 从配置文件中的值进行绑定和bean属性进行绑定

    public class HttpEncodingProperties {...}

根据当前不同条件判断,决定这个配置类是否生效?

一旦这个配置类生效;这个配置类会给容器添加各种组件;这些组件的属性是从对应的properties中获取的,这些类里面的每个属性又是和配置文件绑定的。

所有自动配置组件

每一个xxxAutoConfiguration这样的类都是容器中的一个组件,都加入到容器中。

作用:用它们做自动配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

精髓

  1. SpringBoot启动会加载大量的自动配置类

  2. 我们看我们需要的功能有没有SpringBoot默认写好的自动配置类

  3. 如果有,再看这个自动配置类中配置了哪些组件(只要有需要用的组件,就不需要再手动配置);如果有,则需要自己手动配置。

  4. 给容器中自动配置添加组件的时候,会从properties类中获取属性。我们就可以在配置文件中指定这些属性的值

xxxAutoConfiguration:自动配置类,给容器中添加组件。

xxxProperties:封装配置文件中的属性。

细节

  • @Conditional派生注解

    利用Spring注解版原生的@Conditional注解

    作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效。

@Conditional派生注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean
@ConditionalOnMissBean 容器中不存在指定Bean
@ConditionalOnExpression 满足spEL表达式
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定的资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项
  • 自动配置报告

    自动配置类必须在一定条件下生效。

    我们可以通过启用debug=true属性,配置文件,打印自动配合报告,这样就可以知道自动配置类生效。

    自动配置报告:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    ============================

    CONDITIONS EVALUATION REPORT
    ============================

    Positive matches:(启动的,匹配成功的)
    -----------------

    CodecsAutoConfiguration matched:
    - @ConditionalOnClass found required class 'org.springframework.http.codec.CodecConfigurer'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
    ......

    Negative matches:(没有启动的,没有匹配成功的)
    -----------------

    ActiveMQAutoConfiguration:
    Did not match:
    - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
    ......

日志

日志框架

日志抽象层 日志实现
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging Log4j JUL(java.util.logging) Log4j2 Logback

选用SLF4J + Logback

SpringBoot的底层是Spring框架,使用的JCL,SpringBoot改用了SLF4J。

SLF4J的使用

如何在系统中使用SLF4J

以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法。

应该给系统里面导入slf4j的jar包和logback的实现jar包。

1
2
3
4
5
6
7
8
9
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
SLF4J具体绑定
SLF4J具体绑定

每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架的配置文件

遗留问题

如开发a系统(slf4j+logback):Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis……

c

如何让系统中所有日志统一到slf4j?

  1. 将系统中其他日志框架排除出去

  2. 用中间包来替换原有的日志框架

  3. 导入slf4j的其他实现

SpringBoot日志关系

SpringBoot的日志功能:

1
2
3
4
5
6
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.0.1.RELEASE</version>
<scope>compile</scope>
</dependency>
SpringBoot日志关系
SpringBoot日志关系

总结:

  1. SpringBoot底层也是使用slf4jJ+logback

  2. SpringBoot也把其他日志替换成了slf4j

  3. 起着commons.loggings的名字其实new的SLF4J替换中间包

  4. 如果要引入其他框架?一定要把这个框架的默认日志依赖移除掉

日志使用

默认配置

trace-debug-info-warn-error

可以调整需要的日志级别进行输出,不用注释语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 记录器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
// 日志的级别
// 从低到高
// 可以调整输出的日志级别;日志就只会在这个级别以后的高级别生效
logger.trace("这是trace日志");
logger.debug("这是debug信息");
// SpringBoot默认给的是info级别,如果没指定就是默认的root级别
logger.info("这是info日志");
logger.warn("这是warn信息");
logger.error("这是Error信息");
}

调整指定包的日志级别在配置文件中进行配置:

1
logging.level.com.gxk=trace

日志输出格式:

1
2
3
4
5
6
7
8
#控制台输出的日志格式 
#%d:日期
#%thread:线程号
#%-5level:靠左 级别
#%logger{50}:全类名50字符限制,否则按照句号分割
#%msg:消息+换行
#%n:换行
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

SpringBoot修改日志的默认配置:

1
2
3
4
5
6
7
8
9
logging.level.com.gxk=trace
#不指定path就是当前目录下生成springboot.log
#logging.file=springboot.log
#当前磁盘下根路径创建spring文件中log文件夹,使用spring.log作为默认
logging.path=/spring/log
#控制台输出的日志格式 日期 + 线程号 + 靠左 级别 +全类名50字符限制+消息+换行
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
#指定文件中日志输出的格式
logging.pattern.file=xxx

指定配置

给类路径下放上每个日志框架自己的配置文件,SpringBoot就不会使用默认的配置

logging System Customization
Logback logback-spring.xml,logback-spring.groovy,logback.xml or logback.groovy
Log4J2 log4j2-spring.xml or log4j2.xml
JDK(Java Util Logging) logging.properties

logback.xml直接被logback日志框架识别 ,logback-spring.xml先由SpringBoot识别。

1
2
3
<springProfile name="dev">
<!-- 可以指定某段配置只在某个环境下生效 -->
</springProfile>

使用参数 --spring.profiles.active=dev运行,即使用这段配置。

切换日志框架

  1. logback → log4j

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
    <exclusion>
    <artifactId>logback-classic</artifactId>
    <groupId>ch.qos.logback</groupId>
    </exclusion>
    </exclusions>
    </dependency>

    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    </dependency>
  2. 切换为log4j2的starter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
    <exclusion>
    <artifactId>spring-boot-starter-logging</artifactId>
    <groupId>org.springframework.boot</groupId>
    </exclusion>
    </exclusions>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>